<template>
  <div class="box">
    <CardItem v-for="(mm, index) in members" :key="index" :mm="mm" />

    <CardItem :mm="me">
      <text class="tips">{{ tips }}</text>
      <template #ext>
        <text :class="[tips, { en: lan == 'en' }]">具名插槽，一切顺利</text>
      </template>
    </CardItem>

    <text class="lan" @click="changeLan">中英切换 {{ lan }}</text>
    <!-- 给 DOM 元素添加 `ref` 属性 -->
    <div ref="btn">语言检测中</div>
    <div v-html="html"></div>
    <span v-text="tips"></span>
  </div>
</template>

<script lang="ts">
import {
  defineComponent,
  onBeforeMount,
  onBeforeUnmount,
  onBeforeUpdate,
  onErrorCaptured,
  onMounted,
  onUnmounted,
  onUpdated,
  ref,
  reactive,
  toRef,
  watch,
  watchEffect,
  computed,
} from "vue";
import { add, reduce } from "../common/util";
import { cn_members, cn_me } from "../common/cn";
import { en_members } from "../common/en";
import CardItem from "./CardItem.vue";
import type { MemberType } from "../common/type";

export default defineComponent({
  components: {
    CardItem,
  },
  setup(props, context) {
    console.log("--父组件参数： props--", props);
    console.log("--组件执行上下文：context--", context);
    // emit: 触发父组件绑定事件
    const { attrs, slots, emit } = context;
    // ref变量
    const btn = ref<HTMLElement>();
    const name = ref<string>("Steve Jobs");
    const desc = ref<string>("Co-founder of Apple");
    const age = ref<number>(58);
    const lan = ref<string>("en");
    const members = ref<MemberType[]>(en_members);
    // reactive变量
    const me: MemberType = reactive(cn_me);

    // 创建一个新的 Ref 变量，转换 Reactive 对象的某个字段为 Ref 变量
    const meName = toRef(me, "name");
    meName.value = "Susan";

    // setup: 创建组件之前执行
    // 放置业务代码
    // 不能再用this来获取实例
    // 生命周期函数统一放在setup里
    onBeforeMount(() => {
      console.log("1-onBeforeMount: ", "组件挂载到节点上之前执行");
    });
    onMounted(() => console.log("2-onMounted: ", "组件挂载完成后执行"));
    onBeforeUpdate(() => console.log("3-onBeforeUpdate: ", "组件更新之前执行"));
    onUpdated(() => console.log("4-onUpdated: ", "组件更新完成之后执行"));
    onBeforeUnmount(() =>
      console.log("5-onBeforeUnmount: ", "组件卸载之前执行")
    );
    onUnmounted(() => console.log("6-onUnmounted", "组件卸载完成后执行"));
    onErrorCaptured(() =>
      console.log("7-onErrorCaptured", "捕获来自子孙组件的异常时激活该钩子函数")
    );

    // 给template使用的变量或方法必须导出
    function changeLan() {
      if (lan.value == "en") {
        members.value = cn_members;
        lan.value = "cn";
        // me = cn_me;

        if (btn.value) {
          btn.value.innerText = "中文";
        }
      } else {
        members.value = en_members;
        lan.value = "en";
        // me = en_me;

        if (btn.value) {
          btn.value.innerText = "Egnlish";
        }
      }
    }

    // 侦听 类似于useEffect 监听某些变化后 do something
    const handleWatch = (newValue: string, oldValue: string): void => {
      console.log("--侦听原数据--", oldValue);
      console.log("--侦听新数据--", newValue);
    };
    // 监听现有字段 然后执行副作用
    watch(name, handleWatch);
    watch(desc, handleWatch);
    watch([name, desc], () => {
      console.log("批量侦听");
    });
    // 默认侦听执行函数中涉及到的所有变量，只要有变化就会执行
    watchEffect(() => {
      console.log("watch name", name);
      console.log("watch desc", desc);
    });

    // 计算函数 返回一个新的变量
    const firstName = ref<string>("hong");
    const secondName = ref<string>("diandian");
    const fullName = computed(() => `${firstName.value}.${secondName.value}`);

    // v-html
    const html = ref<string>("<text>你好，世界！</text>");

    // v-text
    const tips = ref<string>("温馨提示：请务必热爱生活！");

    // 需要在template中使用的数据必须return回去
    return {
      add,
      reduce,
      changeLan,
      name,
      desc,
      age,
      lan,
      members,
      btn,
      me,
      fullName,
      html,
      tips,
    };
  },
});
</script>

<style scoped>
.box {
  display: flex;
  flex-direction: column;
}

.lan {
  margin: 10px 0;
  cursor: pointer;
  font-size: 12px;
}

.tips {
  color: #666;
  font-size: 12px;
}

.tips::before {
  content: "*";
  color: red;
}

.en {
  background-color: rgba(0, 0, 0, 0.02);
}
</style>
